package com.example.demo.config.myannotation.code.aop;


import com.example.demo.config.myannotation.code.LogAnno.LogAnno;
import com.example.demo.config.myannotation.code.command.HttpContextUtil;
import com.example.demo.config.myannotation.entity.Log;
import com.example.demo.config.myannotation.mapper.logMapper;
import com.example.demo.mapper.TokenMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

@Order(3)
@Component
@Aspect
public class LohAopect {

    @Autowired
    private logMapper mapper;
    @Autowired
    private TokenMapper tokenMapper;

    /**
     * 通过环形方法将自定义注解调用的方法记录到数据库
     * @param pip
     * @return
     * @throws Throwable
     */
    @Around("@annotation(com.example.demo.config.myannotation.code.LogAnno.LogAnno)")
    public Object aroundAdive(ProceedingJoinPoint pip) throws Throwable{
        //1.获取方法签名
        MethodSignature methodSignature = (MethodSignature)pip.getSignature();

        //2.获取方法名称
        Method method = methodSignature.getMethod();

        //3.获取注解
        LogAnno logAnno = method.getAnnotation(LogAnno.class);

        //4.获取操作描述
         String operType = logAnno.operatType();

         //5.创建日志对象
        Log log = new Log();
        log.setOperation(operType);

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
        .getRequest();
        String token = request.getHeader("token");
        if (token == null)
            log.setUsername("Do Not Have Token In Header");
        else
            log.setUsername(tokenMapper.findUserName(token));

        log.setIp(HttpContextUtil.getIpAddress());

        //方法获取
        String className = pip.getTarget().getClass().getName();
        String meth = methodSignature.getName();
        log.setMethod(className + "." + meth + "()");

        //参数获取
        Object[] args = pip.getArgs();
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        String[] parmName = u.getParameterNames(method);
        if (args != null && parmName != null) {
            String parm = "";
            for (int i = 0; i < args.length; i++) {
                parm += " " + parmName[i] + ":" + args[i];
            }
            log.setParams(parm);
        }
        //获取执行方法时间
        Object result = null;
            long stTime = System.currentTimeMillis();
            result = pip.proceed(); //执行调用接口的方法
            long edTime = System.currentTimeMillis() - stTime;
            log.setTime(edTime);
        log.setCreatetime(new Date());

        //保存数据
        mapper.insert(log);

        return result;
    }
}
